/**
 * 文档管理模块 - 图片上传组件
 * Phase 3: MinIO 前端集成
 * 
 * 功能：
 * - 文件选择（File Input）
 * - 拖拽上传（Drag & Drop）
 * - 粘贴上传（Clipboard API）
 * - 上传前预览
 * - 上传进度显示
 * - 图片压缩（browser-image-compression）
 * - 错误处理
 */

import React, { useState, useRef, useCallback } from 'react';
import { Button } from '@/components/ui/button';
import { Progress } from '@/components/ui/progress';
import { Upload, X, Image as ImageIcon, Loader2, CheckCircle2, AlertCircle, File } from 'lucide-react';
import { fileService } from '@/lib/api/services/file-service';
import { cn } from '@/lib/utils';

// 动态导入图片压缩库（如果已安装）
let imageCompression = null;
try {
  imageCompression = require('browser-image-compression');
} catch (e) {
  console.warn('browser-image-compression 未安装，图片压缩功能不可用');
}

/**
 * 图片上传组件
 * @param {object} props
 * @param {Function} props.onSuccess - 上传成功回调 (fileMetadata) => void
 * @param {Function} props.onError - 上传失败回调 (error) => void
 * @param {Function} props.onProgress - 上传进度回调 (percent) => void
 * @param {string} props.documentId - 关联的文档ID
 * @param {string} props.fileType - 文件类型：image/document/avatar/cover
 * @param {boolean} props.compress - 是否压缩图片，默认 true
 * @param {number} props.maxSizeMB - 最大文件大小（MB），默认 10
 * @param {string} props.accept - 接受的文件类型，默认 "image/*"
 * @param {boolean} props.multiple - 是否支持多文件，默认 false
 * @param {string} props.uploadSource - 上传来源：editor（Monaco编辑器）/attachment（文档附件）/manual（手动上传），默认 'attachment'
 * @param {string} props.className - 自定义样式类
 */
const ImageUploader = ({
  onSuccess,
  onError,
  onProgress,
  documentId,
  fileType = 'image',
  compress = true,
  maxSizeMB = 10,
  accept = 'image/*',
  multiple = false,
  uploadSource = 'attachment',
  className = ''
}) => {
  const [dragActive, setDragActive] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [preview, setPreview] = useState(null);
  const [uploadingFileName, setUploadingFileName] = useState(null); // 上传中的文件名
  const [error, setError] = useState(null);
  const fileInputRef = useRef(null);
  const abortControllerRef = useRef(null);

  /**
   * 验证文件
   * @param {File} file - 文件对象
   * @returns {boolean} 是否有效
   */
  const validateFile = useCallback((file) => {
    // 根据 fileType 决定验证逻辑
    if (fileType === 'image') {
      // 图片类型：只接受图片文件
      if (!file.type.startsWith('image/')) {
        setError('只支持图片文件');
        return false;
      }
    } else {
      // 文档类型或其他：根据 accept prop 验证（如果提供了）
      // 如果 accept 是 '*/*'，则接受所有文件类型
      if (accept && accept !== '*/*') {
        // 简单的 MIME 类型匹配（可以扩展为更复杂的验证）
        const acceptedTypes = accept.split(',').map(t => t.trim());
        const isAccepted = acceptedTypes.some(type => {
          if (type.endsWith('/*')) {
            // 通配符匹配，如 "image/*"
            const prefix = type.slice(0, -2);
            return file.type.startsWith(prefix);
          } else {
            // 精确匹配
            return file.type === type;
          }
        });
        
        if (!isAccepted) {
          setError(`不支持的文件类型：${file.type}`);
          return false;
        }
      }
    }

    // 检查文件大小
    const maxSizeBytes = maxSizeMB * 1024 * 1024;
    if (file.size > maxSizeBytes) {
      setError(`文件大小不能超过 ${maxSizeMB}MB`);
      return false;
    }

    setError(null);
    return true;
  }, [maxSizeMB, fileType, accept]);

  /**
   * 压缩图片
   * @param {File} file - 原始文件
   * @returns {Promise<File>} 压缩后的文件
   */
  const compressImage = useCallback(async (file) => {
    // 只压缩图片类型的文件
    if (fileType !== 'image' || !compress || !imageCompression) {
      return file;
    }

    try {
      const options = {
        maxSizeMB: maxSizeMB,
        maxWidthOrHeight: 1920,
        useWebWorker: true,
        fileType: 'image/jpeg'
      };

      const compressedFile = await imageCompression.default(file, options);
      console.log(`图片压缩: ${(file.size / 1024 / 1024).toFixed(2)}MB → ${(compressedFile.size / 1024 / 1024).toFixed(2)}MB`);
      return compressedFile;
    } catch (error) {
      console.warn('图片压缩失败，使用原文件:', error);
      return file;
    }
  }, [compress, maxSizeMB, fileType]);

  /**
   * 创建预览
   * @param {File} file - 文件对象
   */
  const createPreview = useCallback((file) => {
    // 只对图片文件创建预览
    if (fileType === 'image' && file.type.startsWith('image/')) {
      const url = URL.createObjectURL(file);
      setPreview(url);
      return url;
    }
    // 非图片文件不创建预览，返回 null
    setPreview(null);
    return null;
  }, [fileType]);

  /**
   * 上传文件
   * @param {File} file - 文件对象
   */
  const uploadFile = useCallback(async (file) => {
    if (!validateFile(file)) {
      return;
    }

    setUploading(true);
    setUploadProgress(0);
    setError(null);
    setUploadingFileName(file.name); // 保存文件名

    // 创建预览（仅图片文件）
    const previewUrl = createPreview(file);

    // 创建 AbortController 用于取消上传
    abortControllerRef.current = new AbortController();

    try {
      // 压缩图片（如果启用且是图片类型）
      const fileToUpload = await compressImage(file);

      // 上传参数
      const uploadParams = {
        fileType: fileType,
        documentId: documentId,
        compress: compress && fileType === 'image', // 只对图片压缩
        generateThumbnail: fileType === 'image', // 只对图片生成缩略图
        uploadSource: uploadSource  // 传递上传来源
      };

      // 上传文件
      const fileMetadata = await fileService.upload(
        fileToUpload,
        uploadParams,
        (percent) => {
          setUploadProgress(percent);
          onProgress && onProgress(percent);
        }
      );

      // 清理预览 URL（如果存在）
      if (previewUrl) {
        URL.revokeObjectURL(previewUrl);
      }
      setPreview(null);
      setUploadingFileName(null);

      // 成功回调
      onSuccess && onSuccess(fileMetadata);
      setUploading(false);
      setUploadProgress(0);
    } catch (error) {
      // 清理预览 URL（如果存在）
      if (previewUrl) {
        URL.revokeObjectURL(previewUrl);
      }
      setPreview(null);
      setUploadingFileName(null);

      const errorMessage = error.message || '上传失败';
      setError(errorMessage);
      onError && onError(error);
      setUploading(false);
      setUploadProgress(0);
    }
  }, [validateFile, compressImage, createPreview, fileType, documentId, compress, uploadSource, onSuccess, onError, onProgress]);

  /**
   * 处理文件选择
   * @param {FileList} files - 文件列表
   */
  const handleFiles = useCallback((files) => {
    if (!files || files.length === 0) return;

    const file = files[0]; // 单文件上传
    uploadFile(file);
  }, [uploadFile]);

  /**
   * 处理拖拽事件
   */
  const handleDrag = useCallback((e) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.type === 'dragenter' || e.type === 'dragover') {
      setDragActive(true);
    } else if (e.type === 'dragleave') {
      setDragActive(false);
    }
  }, []);

  /**
   * 处理拖拽放下
   */
  const handleDrop = useCallback((e) => {
    e.preventDefault();
    e.stopPropagation();
    setDragActive(false);

    if (e.dataTransfer.files && e.dataTransfer.files[0]) {
      handleFiles(e.dataTransfer.files);
    }
  }, [handleFiles]);

  /**
   * 处理文件选择
   */
  const handleFileSelect = useCallback((e) => {
    if (e.target.files && e.target.files[0]) {
      handleFiles(e.target.files);
    }
    // 重置 input，允许重复选择同一文件
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  }, [handleFiles]);

  /**
   * 处理粘贴事件
   */
  const handlePaste = useCallback((e) => {
    const items = e.clipboardData?.items;
    if (!items) return;

    for (let i = 0; i < items.length; i++) {
      const item = items[i];
      if (item.type.startsWith('image/')) {
        const file = item.getAsFile();
        if (file) {
          handleFiles([file]);
          e.preventDefault();
          break;
        }
      }
    }
  }, [handleFiles]);

  /**
   * 取消上传
   */
  const handleCancel = useCallback(() => {
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
    }
    setUploading(false);
    setUploadProgress(0);
    setPreview(null);
    setUploadingFileName(null);
    setError(null);
  }, []);

  // 监听粘贴事件（仅图片类型）
  React.useEffect(() => {
    if (fileType === 'image' && !uploading) {
      document.addEventListener('paste', handlePaste);
      return () => {
        document.removeEventListener('paste', handlePaste);
      };
    }
  }, [uploading, handlePaste, fileType]);

  return (
    <div className={cn('space-y-4', className)}>
      {/* 上传区域 */}
      {!uploading && !preview && (
        <div
          className={cn(
            'border-2 border-dashed rounded-lg p-8 text-center transition-colors cursor-pointer',
            dragActive
              ? 'border-primary bg-primary/5'
              : 'border-muted-foreground/25 hover:border-muted-foreground/50'
          )}
          onDragEnter={handleDrag}
          onDragLeave={handleDrag}
          onDragOver={handleDrag}
          onDrop={handleDrop}
          onClick={() => fileInputRef.current?.click()}
        >
          <div className="space-y-3">
            <Upload className="size-10 mx-auto text-muted-foreground" />
            <div className="text-sm text-muted-foreground">
              <p className="font-medium">
                {fileType === 'image' ? '拖拽图片到此处或点击选择' : '拖拽文件到此处或点击选择'}
              </p>
              <p className="text-xs mt-1">
                {fileType === 'image' 
                  ? `支持 JPG、PNG、GIF、WebP 格式，最大 ${maxSizeMB}MB`
                  : accept === '*/*'
                    ? `支持所有文件格式，最大 ${maxSizeMB}MB`
                    : `支持 ${accept} 格式，最大 ${maxSizeMB}MB`}
              </p>
            </div>
            <input
              ref={fileInputRef}
              type="file"
              accept={accept}
              multiple={multiple}
              onChange={handleFileSelect}
              className="hidden"
            />
          </div>
        </div>
      )}

      {/* 上传中状态 */}
      {uploading && (
        <div className="space-y-3">
          {preview ? (
            // 图片预览
            <div className="relative rounded-lg overflow-hidden border">
              <img
                src={preview}
                alt="预览"
                className="w-full h-48 object-cover"
              />
              <div className="absolute inset-0 bg-black/50 flex items-center justify-center">
                <Loader2 className="size-8 text-white animate-spin" />
              </div>
            </div>
          ) : uploadingFileName ? (
            // 非图片文件显示文件名
            <div className="rounded-lg border p-4 bg-muted/50">
              <div className="flex items-center gap-3">
                <File className="size-8 text-muted-foreground" />
                <div className="flex-1 min-w-0">
                  <p className="font-medium text-sm truncate" title={uploadingFileName}>
                    {uploadingFileName}
                  </p>
                  <p className="text-xs text-muted-foreground mt-1">正在上传...</p>
                </div>
                <Loader2 className="size-5 text-muted-foreground animate-spin" />
              </div>
            </div>
          ) : null}
          <div className="space-y-2">
            <div className="flex items-center justify-between text-sm">
              <span className="text-muted-foreground">上传中...</span>
              <span className="font-medium">{uploadProgress}%</span>
            </div>
            <Progress value={uploadProgress} className="h-2" />
            <Button
              variant="outline"
              size="sm"
              onClick={handleCancel}
              className="w-full"
            >
              取消上传
            </Button>
          </div>
        </div>
      )}

      {/* 错误提示 */}
      {error && (
        <div className="flex items-center gap-2 p-3 rounded-lg bg-destructive/10 text-destructive text-sm">
          <AlertCircle className="size-4" />
          <span>{error}</span>
          <Button
            variant="ghost"
            size="sm"
            onClick={() => setError(null)}
            className="ml-auto h-auto p-0"
          >
            <X className="size-4" />
          </Button>
        </div>
      )}

      {/* 使用说明（仅图片类型显示粘贴提示） */}
      {!uploading && !preview && fileType === 'image' && (
        <div className="text-xs text-muted-foreground text-center">
          <p>💡 提示：也可以使用 Ctrl+V 粘贴剪贴板中的图片</p>
        </div>
      )}
    </div>
  );
};

export default ImageUploader;

